﻿using Blog.Core.Domain.Model.User;
using Blog.Core.DTO.ViewModel;
using Blog.Core.DTO.ViewModel.User;
using Blog.Core.IRepositories.IUser;
using Blog.Core.IServices.IUser;
using MD5Hash;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using Blog.Core.DTO;
using Blog.Core.IRepositories;
using Blog.Core.Repositories;
using Blog.Core.EFcore;
//using Blog.Core.EFcore.Migrations;
using Blog.Core.Repositories.User;
using System.Runtime.CompilerServices;

using System.Net.Http.Json;
using System.Security;
using System.Text.Json.Serialization;
using Newtonsoft.Json;  //序列化
using System.Security.Permissions;
using System.ComponentModel;


namespace Blog.Core.Services.User
{
    /// <summary>
    /// 用户信息服务
    /// </summary>
    public class UserService : BaseService<UserInfo>, IUserService
    {
        /// <summary>
        /// 依赖注入
        /// </summary>
        private readonly IUnOfWork unOfWork;
        private readonly IUserInfoRepository userInfoRepositories;//用户信息表
        private readonly IRoleUserRepository roleUserRepositories;
        private readonly IRolesRepository rolesRepository;
        private readonly IPermissionsRepository permissionsRepository;
        private readonly IRolePermissionRepository rolePermissionRepository;
        private readonly IMapper mapper;

        public UserService(IRepository<UserInfo> repository, IUnOfWork unOfWork, IUserInfoRepository userInfoRepositories, IRoleUserRepository roleUserRepositories, IRolesRepository rolesRepository, IPermissionsRepository permissionsRepository, IRolePermissionRepository rolePermissionRepository,  IMapper mapper) : base(repository, unOfWork)
        {
            this.userInfoRepositories = userInfoRepositories;
            this.roleUserRepositories = roleUserRepositories;
            this.rolesRepository = rolesRepository;
            this.permissionsRepository = permissionsRepository;
            this.rolePermissionRepository = rolePermissionRepository;
            this.mapper = mapper;
            this.unOfWork = unOfWork;
        }
        /// <summary>
        /// 权限过滤器获取用户所对应的权限
        /// </summary>
        /// <param name="UserId"></param>
        /// <returns></returns>
        public async Task<List<Permissions>> GetUserPermissions(int UserId)
        {
            List<int> roleIds = (await roleUserRepositories.GetAll()).Where(x => x.UserId == UserId).Select(x => x.RoleId).ToList();
            List<Permissions> list = new List<Permissions>();
            foreach (var item in roleIds)
            {
                list.AddRange(GetRoleToPermission((int)item).Result);
            }
            //对权限信息进行去重
            list = list.Distinct().ToList();
            return list;
        }

        /// <summary>
        /// 用于获取用户已授权的功能列表.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<List<MenuTreeDto>> GetFunctionsByUserId(string UserName)
        {
            var Userid = (await userInfoRepositories.GetAll()).Where(m => m.Login.Equals(UserName)).Select(x => x.Id).FirstOrDefault();
            List<int> roleIds = roleUserRepositories.GetAll().Result.Where(x => x.UserId == Userid).Select(x => x.RoleId).ToList();
            List<Permissions> list=new List<Permissions>();
            foreach (var item in roleIds)
            {
                list.AddRange(GetRoleToPermission((int)item).Result);
            }
            //对权限信息进行去重
            list=list.Distinct().ToList();
            //获取对权限进行菜单来得层级显示，使用递归
            List<MenuTreeDto> menu = RecursionToMenu(0, list);
            return menu;
        }

        /// <summary>
        /// 获取一个角色中所有的权限
        /// </summary>
        /// <param name="roleId"></param>
        /// <returns></returns>
        public async Task<List<Permissions>> GetRoleToPermission(int roleId)
        {
            //获取该角色的全部权限id
            var permissinoIds = (await rolePermissionRepository.GetAll()).Where(m => m.RoleId == roleId).Select(m => m.PermissionId).ToList();
            //根据这些id将这些信息变为权限值信息
            var list=new List<Permissions>();
            foreach (var item in permissinoIds)
            {
                list.Add((await permissionsRepository.GetAll()).Where(m => m.Id == item).ToList().FirstOrDefault());
            }
            return list;
        }

        /// <summary>
        /// 获取对权限进行菜单来得层级显示，使用递归
        /// </summary>
        /// <param name="id"></param>
        /// <param name="list"></param>
        /// <returns></returns>
        public List<MenuTreeDto> RecursionToMenu(int id, List<Permissions> list)
        {
            //实例化dto
            List<MenuTreeDto> dto=new List<MenuTreeDto>();
            //根据父级id查询数据list1
            var list1 = list.Where(x => x.Permissions_Pid == id).ToList();
            //循环数据list1判断是否存在子级
            foreach (var item in list1)
            {
                dto.Add(new MenuTreeDto
                {
                    icon = item.Icon,
                    index = item.RouteId,
                    title = item.PermissionsName,
                    subs = RecursionToMenu(item.Id, list),
                });
            }
            return dto.Count() > 0 ? dto : null;
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ResponseResultDTO<UserInfo>> UserLogin(PostUserLoginDTO dto)
        {
            ResponseResultDTO<UserInfo> result = new ResponseResultDTO<UserInfo>();
            //开启事务
            var tran = unOfWork.GetDbContext().Database.BeginTransaction();
            try
            {
                #region 登录判断
                dto.Pwd = dto.Pwd.GetMD5();
                var entity = await GetByName(dto.Login);
                if (entity == null)
                {
                    //用户名不存在
                    result.Code = ResultStatusCode.HANDLEFAIL;
                    result.Message = "该用户不存在";
                    return result;
                }
                //判断该用户是否还在锁定中
                if (entity.LoseNum >= 3)
                {
                    if (entity.LoseTime > DateTime.Now)
                    {
                        //用户名不存在
                        result.Code = ResultStatusCode.HANDLEFAIL;
                        result.Message = "密码已输错三次，该账户还在锁定，请稍后重试";
                        return result;
                    }
                    else
                    {
                        entity.LoseNum = 0;
                        await userInfoRepositories.Update(entity);
                    }
                }
                if (entity.Pwd != dto.Pwd)
                {
                    //登陆失败后，失败次数+1
                    entity.LoseNum += 1;
                    if (entity.LoseNum >= 3)
                    {
                        entity.LoseTime = DateTime.Now.AddMinutes(5);//登录次数超过三次，锁定客户
                        await userInfoRepositories.Update(entity);
                        await unOfWork.SaveChanges();
                        tran.Commit();
                        //锁定用户
                        result.Code = ResultStatusCode.HANDLEFAIL;
                        result.Message = "密码已输错三次，该账户已锁定，请稍后重试";
                        return result;
                    }
                    else
                    {
                        await userInfoRepositories.Update(entity);
                        await unOfWork.SaveChanges();
                        tran.Commit();
                        result.Code = ResultStatusCode.HANDLEFAIL;
                        result.Message = "密码错误,登录失败";
                        return result;
                    }

                }
                else
                {
                    if (entity.LoseNum >= 3)
                    {
                        if (entity.LoseTime > DateTime.Now)
                        {
                            //锁定用户
                            result.Code = ResultStatusCode.HANDLEFAIL;
                            result.Message = "密码已输错三次，该账户还在锁定，请稍后重试";
                            return result;
                        }
                        else
                        {
                            entity.LoseNum = 0;
                            await userInfoRepositories.Update(entity);
                            await unOfWork.SaveChanges();
                            tran.Commit();
                            //登录成功
                            result.Code = ResultStatusCode.SUCCESS;
                            result.Message = "登录成功，感谢您的支持!!";
                            result.Data = entity;
                        }
                    }
                    else
                    {
                        entity.LoseNum = 0;
                        await userInfoRepositories.Update(entity);
                        await unOfWork.SaveChanges();
                        //事务提交
                        tran.Commit();
                        //登录成功
                        
                    }
                }
                #endregion
                result.Code = ResultStatusCode.SUCCESS;
                result.Message = "登录成功，感谢您的支持!!";
                result.Data = entity;
                return result;


            }
            catch (Exception)
            {
                //事务回滚
                tran.Rollback();
                result.Code = ResultStatusCode.HANDLEFAIL;
                result.Message = "登录失败";
                return result;
                //throw;
            }

        }

        /// <summary>
        /// 根据用户名查到单个
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        private async Task<UserInfo> GetByName(string name)
        {
            var list = await userInfoRepositories.GetAll();
            return list.Where(x => x.Login == name).FirstOrDefault();
        }

        /// <summary>
        /// 用户注册
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<ResponseResultDTO<int>> PostUserInfo(RequestUserDTO entity)
        {
            var list = await userInfoRepositories.GetAll();
            list = list.Where(m => m.Login.Equals(entity.Login)).ToList();
            if (list.Count() > 0)
            {
                return new ResponseResultDTO<int>
                {
                    Code = ResultStatusCode.HANDLEFAIL,
                    Data = list.Count(),
                    Message = "用户名已存在！",//用户名已存在！
                };
            }
            //密码MD5加密
            entity.Pwd = entity.Pwd.GetMD5();
            var user = mapper.Map<UserInfo>(entity);
            user.CreateName = entity.Login;
            user.CreateTime = DateTime.Now.ToLocalTime();

            await userInfoRepositories.Add(user);
            await unOfWork.SaveChanges();
            //添加角色关系
            RoleUsers roleUsers = new RoleUsers()
            {
                RoleId = 1,
                UserId = user.Id,
            };
            await roleUserRepositories.Add(roleUsers);
            await unOfWork.SaveChanges();
            return new ResponseResultDTO<int>
            {
                Code = ResultStatusCode.SUCCESS,
                Message = "注册成功！",//注册成功！
            };
        }

        /// <summary>
        /// 用户密码修改（用户本人修改）
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<ResponseResultDTO<int>> PutUserPwd(UserInfo entity)
        {
            var list = await userInfoRepositories.GetAll();
            var m = list.Where(m => m.Login.Equals(entity.Login)).FirstOrDefault();
            if (m != null)
            {
                //判断密码是否一致
                if (m.Pwd == entity.Pwd.GetMD5())
                {
                    m.Pwd = entity.Pwd.GetMD5();
                    entity.UpdateName = entity.Login;
                    await userInfoRepositories.Update(entity);
                }
                else
                {
                    return new ResponseResultDTO<int>
                    {
                        Code = ResultStatusCode.SUCCESS,
                        Data = list.Count(),
                        Message = "原本密码错误，请重新输入！",
                    };
                }
            }
            else
            {
                return new ResponseResultDTO<int>
                {
                    Code = ResultStatusCode.SUCCESS,
                    Data = list.Count(),
                    Message = "系统错误...请重新修改密码",
                };
            }
            return new ResponseResultDTO<int>
            {
                Code = ResultStatusCode.SUCCESS,
                Data = list.Count(),
                Message = "修改成功！祝您体验愉快！",
            };
        }

        /// <summary>
        /// 用户列表（登录管理员可查看）
        /// </summary>
        /// <param name="pageindex"></param>
        /// <param name="pagesize"></param>
        /// <returns></returns>
        public async Task<PageDTO<GetUserInfoDTO>> GetUserInfo(int pageindex, int pagesize)
        {
            var rolelist = await rolesRepository.GetAll();
            var roleuserlist = await roleUserRepositories.GetAll();
            var list = from x in await userInfoRepositories.GetAll()
                       select new GetUserInfoDTO
                       {
                           Id = x.Id,
                           Phone = x.Phone,
                           Emali = x.Emali,
                           Login = x.Login,
                           UserName = x.UserName,
                           UserImg = x.UserImg,
                           UserId = x.Id,
                           CreateName = x.CreateName,
                           CreateTime = x.CreateTime,
                           UpdateTime = x.UpdateTime,
                           UpdateName = x.UpdateName,
                           Delete = x.Delete,
                           RoleNames = (from y in roleuserlist
                                        join z in rolelist on y.RoleId equals z.Id
                                        where y.UserId.Equals(x.Id)
                                        select new GetUserRoleDTO
                                        {
                                            RoleName = z.RoleName,
                                        }).ToList(),

                       };
            list = list.Where(m => m.Delete == 1);
            //查询角色表全部数据            
            PageDTO<GetUserInfoDTO> data = new PageDTO<GetUserInfoDTO>
            {
                RecordCount = list.Count(),
                Plist = list.OrderBy(m => m.CreateTime).Skip((pageindex - 1) * pagesize).Take(pagesize).ToList(),
            };
            return data;
        }

        /// <summary>
        /// 修改用户个人信息（用户本人修改）
        /// </summary>
        /// <returns></returns>
        public async Task<ResponseResultDTO<int>> PutUserInfo(UserInfo entity)
        {
            //修改人为用户本人账号
            entity.UpdateName = entity.Login;
            //修改时间为当前本地时间
            entity.UpdateTime = DateTime.Now;
            await userInfoRepositories.Update(entity);
            await unOfWork.SaveChanges();
            return new ResponseResultDTO<int>
            {
                Code = ResultStatusCode.SUCCESS,
                Data = entity.Id,
                Message = "编辑成功！祝您体验愉快！",
            };
        }

        /// <summary>
        /// 获取用户单条信息（用于用户编辑个人信息使用）
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<GetUserInfoDTO> GetUserInfoById(int id)
        {
            var list = await userInfoRepositories.GetById(id);
            GetUserInfoDTO dto = new GetUserInfoDTO()
            {
                Id = list.Id,
                Login = list.Login,
                UserName = list.UserName,
                Emali = list.Emali,
                UserImg = list.UserImg,
                Phone = list.Phone,
            };
            return dto;
        }

        /// <summary>
        /// 删除（管理员删除（删除用户））
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<ResponseResultDTO<int>> DeleteUserInfo(int id)
        {
            //调用查询单条数据
            var list = await userInfoRepositories.GetById(id);
            //逻辑删除
            list.Delete = 0;
            await userInfoRepositories.Update(list);
            List<RoleUsers> m = await roleUserRepositories.GetAll();
            var n = m.Where(m => m.UserId.Equals(id));
            foreach (var item in n)
            {
                await roleUserRepositories.Delete(item.Id);
            }
            //调用工作单元
            await unOfWork.SaveChanges();
            return new ResponseResultDTO<int>
            {
                Code = ResultStatusCode.SUCCESS,
                Data = n.Count(),
                Message = "删除成功!",//删除成功！
            };
        }

        /// <summary>
        /// 删除（个人进行删除（账号注销））
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<ResponseResultDTO<int>> DeleteUserInfos(GetUserDeleteDTO dto)
        {   
            //调用查询单条数据
            var list = await userInfoRepositories.GetById(dto.Id);
            //判断密码是否正确
            if(list.Pwd!=dto.Pwd)
            {
                //密码不正确，则返回注销失败！
                return new ResponseResultDTO<int>
                {
                    Code = ResultStatusCode.SUCCESS,
                    Message = "密码错误，注销失败！",//密码错误，注销失败！
                };
            }
            //逻辑删除
            list.Delete = 0;
            list.UpdateTime = DateTime.Now;
            list.UpdateName = list.Login;
            await userInfoRepositories.Update(list);
            List<RoleUsers> m = await roleUserRepositories.GetAll();
            var n = m.Where(m => m.UserId.Equals(dto.Id));
            foreach (var item in n)
            {
                await roleUserRepositories.Delete(item.Id);
            }
            //调用工作单元
            await unOfWork.SaveChanges();
            return new ResponseResultDTO<int>
            {
                Code = ResultStatusCode.SUCCESS,
                Data = n.Count(),
                Message = "注销成功!",//删除成功！
            };
        }

        /// <summary>
        /// 添加角色
        /// 用户修改（管理员进行修改）
        /// </summary>
        /// <param name="enity"></param>
        /// <returns></returns>
        public async Task<ResponseResultDTO<int>> PutUserInfos(RoleUserDTO dto)
        {
            //先把用户的角色删除
            var list = await roleUserRepositories.GetAll();
            var m = list.Where(x => x.UserId == dto.UserId);
            foreach (var item in m)
            {
                roleUserRepositories.Delete(item.Id);
            }
            await unOfWork.SaveChanges();
            var n = dto.RoleId;
            //重新给用户分配角色，添加角色
            foreach (var item in n)
            {
                roleUserRepositories.Add(new RoleUsers { RoleId = item, UserId = dto.UserId });
            }
            await unOfWork.SaveChanges();
            return new ResponseResultDTO<int>
            {
                Code = ResultStatusCode.SUCCESS,
                Message = "修改成功",
            };
        }
        /// <summary>
        /// 刷新令牌需要的生成密码
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<RequestUserDTO> GetUserByNameAndPwd(PostUserLoginDTO dto)
        {

            RequestUserDTO result = null;
            //获取Md5字符串
            string pwdMd5 = dto.Pwd.GetMD5();
            UserInfo user = await GetByName(dto.Login);
            if (user.Pwd != pwdMd5)
            {
                user = null;
            }
            if (user != null)
            {
                //result = new UserDto
                //{
                //    Account = user.Account,
                //    Status = user.Status,
                //    UId = user.UId,
                //    UName = user.UName
                //};
                result = mapper.Map<RequestUserDTO>(user); //使用AutoMapper进行对象间映射，“偷懒”
            }
            return result;
        }
        
    }
       
}
    





